/*
** cludp_echo.c
*/

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/times.h>
#include <unistd.h>

/* PORTA UTILIZADA */
#define PORT 3477  

/* NUMERO MAXIMO DE BYTES ENVIADOS/RECEBIDOS POR VEZ */
#define MAXDATASIZE 100

#define TIMEOUT 5

int recvfromtimeout(int sockfd, char *buf, int len, struct sockaddr *their_addr, socklen_t *addr_len, int timeout) {
  fd_set fds;
  int n;
  struct timeval tv;
  
  FD_ZERO(&fds);
  FD_SET(sockfd, &fds);
  
  tv.tv_sec = timeout;
  tv.tv_usec = 0;
  
  n = select(sockfd+1, &fds, NULL, NULL, &tv);
  if (n == 0) return -2; // timeout!
  if (n == -1) return -1; // error
  
  return recvfrom(sockfd, buf, len, 0, their_addr, addr_len);
}

int main(int argc, char *argv[]) {
  int sockfd, numbytes;
  int sent_nl=0;
  int tschar=0, bgst_line=0;
  clock_t TI, TE;
  float TT;
  char buf[MAXDATASIZE];
  socklen_t addr_len = sizeof(struct sockaddr);
  struct hostent *he;
  struct sockaddr_in their_addr; 

  if (argc != 2) {
    fprintf(stderr,"usage: client hostname\n");
    exit(1);
  }
  if ((he=gethostbyname(argv[1])) == NULL) { 
    perror("gethostbyname");
    exit(1);
  }
  if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    perror("socket");
    exit(1);
  }

  their_addr.sin_family = AF_INET;    // AF_UNSPEC ?                     
  their_addr.sin_port   = htons(PORT);                      
  their_addr.sin_addr   = *((struct in_addr *)he->h_addr);
  bzero(&(their_addr.sin_zero), 8);                        
    
  /* "CONECTANDO" O CLIENTE */
  if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
    perror("connect");
    exit(1);
  }

  //                             //
  /* INICIO DA CONTAGEM DO TEMPO */
  //                             //
  TI = times (NULL);

  while (fgets (buf, MAXDATASIZE, stdin)) {

    // envio dos datagramas
    if ((numbytes = send(sockfd, buf, strlen(buf), 0)) == -1) {
      perror("sendto");
      exit(1);
    }

    // contabilidade dos dados
    sent_nl++;
    tschar += numbytes;
    if (numbytes > bgst_line)
      bgst_line = numbytes;
      
    // recebimento do eco e impressao em stdout
    if (recv(sockfd, buf, MAXDATASIZE, 0) == -1) {
      perror("recvfrom");
      exit(1);
    }
 
    printf("%s", buf);
  }

  if ((numbytes = send(sockfd, buf, 0, 0)) == -1) {
    perror("sendto");
    exit(1);
  }

  their_addr.sin_family = AF_UNSPEC;
  connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr));

  TE = times (NULL);
  //                            //
  /* FINAL DA CONTAGEM DO TEMPO */
  //                            //

  // CALCULO DO TEMPO TOTAL E IMPRESSAO DE DADOS
  TT = (float)(TE - TI)/(float)sysconf(_SC_CLK_TCK);
  fprintf (stderr, "Tempo com connect(): %.lfs\n", TT);
  fprintf (stderr, "Linhas enviadas: %d\nMaior linha: %d\nCaracteres enviados: %d\n", sent_nl, bgst_line, tschar);

  /* FECHA O SOCKET E RETORNA */
  close (sockfd);    
  return 0;   
}
